package com.tc.report.intersect;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.tc.report.DnCell;
import com.tc.report.IntersectReport;
import com.tc.report.ReportAreaHandle;
import com.tc.report.ReportField;
import com.tc.report.ReportIContant;
import com.tc.report.ReportValueNote;
import com.tc.report.StringUtils;

public class IntersectReportImpl implements IntersectReport,ReportIContant{
	/** 报表字段列表,现支持String,Map对象，以便后续扩展
	 * String：代表字段名称，而且该字段对应的结果集为字符串类型。
	 * Map:
	 *  */
	private Map<String,ReportField> fieldMap = new HashMap<String,ReportField>();
	private String fieldNameOfLastRow;
	private String fieldNameOfLastCol;
	private String fieldNameOfLastVal;
	/** 报表查询结果集 */
	private List<Map<String, Object>> queryResult;
	/** 报表行处理器 */
	private ReportAreaHandle rowAreaHandle;
	/** 报表列处理器 */
	private ReportAreaHandle colAreaHandle;
	/** 报表值处理器 */
	private ReportAreaHandle valAreaHandle;
	/** 是否显示行总计 ，默认显示行总计 */
	private boolean isShowRowTotal = true;
	/** 是否显示列总计 ，默认显示列总计 */
	private boolean isShowColTotal = true;
	/** 是否显示显示错误值，如果显示，请设置showErrorValue的值 */
	private boolean isShowErrorValue = false;
	/** 是否显示显示错误值，如果显示，请设置showErrorValue的值 */
	private String showErrorValue="";	
	/** 是否显示显示空白值，如果显示，请设置showBlankValue的值 */
	private boolean isShowBlankValue = true;
	/** 是否显示显示空白值，如果显示，请设置showBlankValue的值 */
	private String showBlankValue="";
	/** 输出方式0-dncell,1-map, 暂未使用*/
	private String outType="";
	/** 
	 * 当前值区域存在多个字段时，用于判断值区域的字段是否显示在行区域，
	 * 默认情况显示在行区域的最后一个字段.
	 * 值区域字段作为行或列区域字段时，不存在该值区域的合计值显示。
	 */
	private boolean isRowFieldOfValue=false;
	
	public boolean isRowFieldOfValue() {
		return isRowFieldOfValue;
	}
	public void setRowFieldOfValue(boolean isRowFieldOfValue) {
		this.isRowFieldOfValue = isRowFieldOfValue;
	}
	public List<Map<String, Object>> getQueryResult() {
		return queryResult;
	}
	public void setQueryResult(List<Map<String, Object>> queryResult) {
		this.queryResult = queryResult;
	}
	public ReportAreaHandle getRowAreaHandle() {
		return rowAreaHandle;
	}
	
	public ReportAreaHandle getColAreaHandle() {
		return colAreaHandle;
	}
	
	public ReportAreaHandle getValAreaHandle() {
		return valAreaHandle;
	}
	
	public boolean isShowRowTotal() {
		return isShowRowTotal;
	}
	public void setShowRowTotal(boolean isShowRowTotal) {
		this.isShowRowTotal = isShowRowTotal;
	}
	public boolean isShowColTotal() {
		return isShowColTotal;
	}
	public void setShowColTotal(boolean isShowColTotal) {
		this.isShowColTotal = isShowColTotal;
	}
	public boolean isShowErrorValue() {
		return isShowErrorValue;
	}
	public void setShowErrorValue(boolean isShowErrorValue) {
		this.isShowErrorValue = isShowErrorValue;
	}
	public String getShowErrorValue() {
		return showErrorValue;
	}
	public void setShowErrorValue(String showErrorValue) {
		this.showErrorValue = showErrorValue;
	}
	public boolean isShowBlankValue() {
		return isShowBlankValue;
	}
	public void setShowBlankValue(boolean isShowBlankValue) {
		this.isShowBlankValue = isShowBlankValue;
	}
	public String getShowBlankValue() {
		return showBlankValue;
	}
	public void setShowBlankValue(String showBlankValue) {
		this.showBlankValue = showBlankValue;
	}
	private ReportField getReportField(String currFieldName, String prevFieldName, String nextFieldName) throws Exception {
		ReportField fieldObj = fieldMap.get(currFieldName);
		if(fieldObj!=null){
			throw new Exception("当前字段已经存在:"+currFieldName);
		}
		fieldObj = new ReportField();
		fieldObj.setFieldName(currFieldName);
		fieldObj.setPreviousFieldName(prevFieldName);
		fieldObj.setNextFieldName(nextFieldName);
		this.fieldMap.put(currFieldName, fieldObj);
		return fieldObj;
	}
	
	public void addRowField(String currFieldName, String prevFieldName, String nextFieldName) throws Exception {
		ReportField fieldObj = getReportField(currFieldName, prevFieldName, nextFieldName);
		if(this.rowAreaHandle==null){
			this.rowAreaHandle = new RowAreaHandle(this);
		}
		this.rowAreaHandle.addReportField(fieldObj);
	}
	
	
	public void addColField(String currFieldName, String prevFieldName, String nextFieldName) throws Exception{
		ReportField fieldObj = getReportField(currFieldName, prevFieldName, nextFieldName);
		if(this.colAreaHandle==null){
			this.colAreaHandle = new ColAreaHandle(this);
		}
		this.colAreaHandle.addReportField(fieldObj);
	}
	
	public void addValField(String currFieldName, String prevFieldName, String nextFieldName) throws Exception{
		ReportField fieldObj = getReportField(currFieldName, prevFieldName, nextFieldName);
		if(this.valAreaHandle==null){
			this.valAreaHandle = new ValAreaHandle(this);
		}
		this.valAreaHandle.addReportField(fieldObj);
	}
	
	
	public void addFieldAtLast(String areaType, String fieldName) throws Exception{
		if(AREATYPE_ROW.equals(areaType)){
			this.addRowField(fieldName, this.fieldNameOfLastRow, "");
			this.fieldNameOfLastRow = fieldName;
		}else if(AREATYPE_COL.equals(areaType)){
			this.addColField(fieldName, this.fieldNameOfLastCol, "");
			this.fieldNameOfLastCol = fieldName;
		}else if(AREATYPE_VAL.equals(areaType)){
			this.addValField(fieldName, this.fieldNameOfLastVal, "");
			this.fieldNameOfLastVal = fieldName;
		}else{
			return;//不支持的类型。
		}		
	}
	
	public void setFieldTitleAlias(String fieldName, String fieldAlias) throws Exception{
		ReportField fieldObj = fieldMap.get(fieldName);
		if(fieldObj!=null){
			fieldObj.setFieldAlias(fieldAlias);
		}
	}
	
	public void setFieldDict(String fieldName, Map<String, Object> dictMap) {
		ReportField fieldObj = fieldMap.get(fieldName);
		if(fieldObj!=null){
			fieldObj.setFieldDict(dictMap);
		}
	}
	
	/**
	 * 处理。
	 */
	public Map<String,Object> findReportResult(List<Map<String,Object>> queryResultList)throws Exception{
		Map<String,Object> resultMap = new HashMap<String,Object>();
		List<DnCell> rowHeadTitleList = null;
		List<List<DnCell>> rowDataList = new ArrayList<List<DnCell>>();
		this.queryResult = queryResultList;//设置报表查询结果。
		int spanRow = getSpanRowOfRowTileCell();//获取标题行的数据.
		for(int index=0;index<spanRow;index++){
			List<DnCell> headList = new ArrayList<DnCell>();
			rowDataList.add(index,headList);
		}
		rowHeadTitleList = this.getRowHeadTitle();//获取行区域标题对象列表。
		rowDataList.set(0, rowHeadTitleList);
		if(this.rowAreaHandle!=null){
			System.out.println("行区域数据处理开始.");
			this.rowAreaHandle.loadQueryResult(queryResultList);//加载数据。
			rowDataList = this.rowAreaHandle.dealAreaDataValue(rowDataList);
			System.out.println("行区域数据处理结束.");
		}else{//无行区域时。
			//TODO		
		}
		if(this.colAreaHandle!=null){
			System.out.println("列区域数据处理开始.");
			this.colAreaHandle.loadQueryResult(queryResultList);
			rowDataList = this.colAreaHandle.dealAreaDataValue(rowDataList);
			System.out.println("列区域数据处理结束.");
		}else{//无列区域时。
			boolean isRowFieldOfValue = this.isRowFieldOfValue();
			int multiple = this.getMultipleOfValArea(isRowFieldOfValue);
			//TODO
		}
		if(this.valAreaHandle!=null){
			System.out.println("值区域数据处理开始.");
			rowDataList = this.valAreaHandle.dealAreaDataValue(rowDataList);
			System.out.println("值区域数据处理结束.");
		}
		resultMap.put(REPORT_RESULT_DNCELL, rowDataList);
		return resultMap;
	}
	
	public List<DnCell> getRowHeadTitle() throws Exception{
		List<DnCell> rowHeadTitleList = new ArrayList<DnCell>();
		if(this.rowAreaHandle!=null){
			//获取行区域首字段。
			ReportField rootField = this.rowAreaHandle.getRootField();
			rowHeadTitleList = getRowHeadTitleCellOfNextField(rowHeadTitleList,rootField);
		}
		int spanRow = getSpanRowOfRowTileCell();//获取标题行的数据.
		DnCell totalCell = new DnCell();
		boolean isRowFieldOfValue = this.isRowFieldOfValue();
		int multiple = this.getMultipleOfValArea(isRowFieldOfValue);
		if(multiple>1){
			totalCell.setFieldValue("数据");
			totalCell.setSpancol(1);//跨列数为1.
			totalCell.setSpanrow(spanRow);
			rowHeadTitleList.add(totalCell);
		}
		return rowHeadTitleList;
	}
	/**
	 * 递归处理行区域的标题单元内容。
	 * @param rowHeadTitleList
	 * @param nextField
	 * @return
	 */
	private List<DnCell> getRowHeadTitleCellOfNextField(List<DnCell> rowHeadTitleList,ReportField nextField){
		String fieldAlias = nextField.getFieldAlias();
		DnCell rowTitleCell = new DnCell();
		rowTitleCell.setFieldValue(fieldAlias);
		int spanNumOfCol = 1;
		int spanNumOfRow = getSpanRowOfRowTileCell();//计算标题头的最大行跨度。
		rowTitleCell.setSpancol(spanNumOfCol);//跨列数为1.
		rowTitleCell.setSpanrow(spanNumOfRow);
		int posX = 0;//单元格X轴坐标。
		int posY = 0;//单元格Y轴坐标。
		if(rowHeadTitleList!=null && rowHeadTitleList.size()>0){
			DnCell lastCell = rowHeadTitleList.get(rowHeadTitleList.size()-1);//最后一个单元
			posY = lastCell.getPosY();//Y轴坐标不变。
			posX = lastCell.getPosX() + 1;//X轴坐标增加一个。
		}
		rowTitleCell.setPosX(posX);
		rowTitleCell.setPosY(posY);
		rowHeadTitleList.add(rowTitleCell);
		//检查是否最后一个字段,如果不是最后一个字段，则递归处理。
		String nextFieldName = nextField.getNextFieldName();
		if(StringUtils.isNotBlank(nextFieldName)){
			ReportField reportField = this.rowAreaHandle.getReportField(nextFieldName);
			rowHeadTitleList = this.getRowHeadTitleCellOfNextField(rowHeadTitleList, reportField);
		}
		return rowHeadTitleList;
	}
	/**
	 * 获取列区域标题单元格的行跨度值。
	 * @return
	 */
	public int getSpanRowOfRowTileCell() {
		int spanNumOfRow = 1;
		if(this.colAreaHandle==null){//如果不存在列区域。
			spanNumOfRow = 1;
		}else{
			//如果存在列区域字段，则行区域标题的字段数就是列区域的字段数。
			spanNumOfRow = this.colAreaHandle.getAreaFieldSize();
			int multiple = this.getMultipleOfValArea(!this.isRowFieldOfValue);//这里需要判断列区域的值标题显示,需要作非处理 .
			if(multiple>1){//如果存在多个值区域字段，而且值区域字段的值显示在列区域中,则行标题的行跨度增加一行。
				spanNumOfRow++;
			}
		}
		return spanNumOfRow;
	}
	/**
	 * 获取行区域标题单元格的列跨度值。
	 * @return
	 */
	public int getSpanColOfRowArea(){
		int spanNumOfCol = 1;
		if(this.rowAreaHandle==null){
			spanNumOfCol = 1;
		}else{
			spanNumOfCol  = this.rowAreaHandle.getAreaFieldSize();
			int multiple = this.getMultipleOfValArea(this.isRowFieldOfValue);//这里需要判断列区域的值标题显示,需要作非处理 .
			if(multiple>1){
				spanNumOfCol++;
			}
		}
		
		return spanNumOfCol;
	}
	
	/**
	 * 判断行区域或列区域是否存在多个值区域的显示字段.
	 * @param isHaveValueField  当该区域包括显示多个值字段时为true,否则为flase.
	 * @return
	 */
	public int getMultipleOfValArea(boolean isHaveValueField){
		ReportAreaHandle valAreaHandle = this.getValAreaHandle();
		int multiple = 1;//值区域的字段个数。
		if(valAreaHandle!=null){//如果不为空，至少存在一个字段。
			if(isHaveValueField){//存在时才需要作倍数处理 。
				multiple = valAreaHandle.getAreaFieldSize();
			}
		}
		return multiple;
	}
	public void setFieldClassifyTotalType(String fieldName, String classifyTotalType) throws Exception {
		ReportField fieldObj = fieldMap.get(fieldName);
		if(fieldObj==null){
			throw new Exception("不存在当前字段："+fieldName);
		}
		fieldObj.setClassifyTotalType(classifyTotalType);
	}
	
	public void addFieldAtLast(String areaType, String fieldName, String fieldAlias) throws Exception {
		this.addFieldAtLast(areaType, fieldName);
		this.setFieldTitleAlias(fieldName, fieldAlias);
	}
	
}
